package org.testis.services;

import org.testis.data.TestStepDataObject;
import org.testis.data.TestStepException;
import org.testis.data.TestStepResultDataObject;
import org.testis.data.TestStepResultDataObjectDistributor;
import org.testis.data.TestStepResultType;
import org.testis.logging.AtofLogLevel;
import org.testis.logging.LogSenderService;
import org.testis.threading.TaskExecutor;

/**
 * A task executor is for handling a thread pool for each module.
 * With this class we can stop running threads, and 
 * checks condition of running threads. Each  module task executor is a singleton
 * and extends this class.So, each module has its own thread pool.
 * @author nurhat
 */
public abstract class AtofModuleTaskExecutor {

    TaskExecutor m_threadExecutorPool;

    /**
     * Creates a task executor and initalize thread pool
     */
    public AtofModuleTaskExecutor() {
        m_threadExecutorPool = new TaskExecutor(1200,
                4000,
                2000,
                Integer.MAX_VALUE);
    }

    /**
     * Any task can be added to thread pool over this method.
     * @param data
     */
    public final void executeTask(TestStepDataObject data) {

        if (!data.isStopExecution()) {
            runTask(data);
        } else {
            cancelTask(data);
        }

    }

    /**
     * Running task for the given dataobject
     * @param data
     */
    private final void runTask(TestStepDataObject data) {
        TestStepResultDataObject res = null;
        String className = super.getClass().getSimpleName();
        try {
            AtofModuleTaskFactory factory = new AtofModuleTaskFactory();
            AtofModuleTask task =
                    factory.getInstance(data);
            m_threadExecutorPool.addTask(task);
        } catch (TestStepException ex) {
            LogSenderService.putMessageOnQueue(
                    className,
                    AtofLogLevel.ERROR,
                    "Test step failed.Error:" + ex.toString(),
                    data.getMessageId());
            res = new TestStepResultDataObject(data);
            res.setResultType(ex.getResultType());
        } catch (Exception ex) {
            LogSenderService.putMessageOnQueue(
                    className,
                    AtofLogLevel.ERROR,
                    "Test step failed.Error:" + ex.toString(),
                    data.getMessageId());
            res = new TestStepResultDataObject(data);
            res.setResultType(TestStepResultType.FAILURE);
        } finally {
            if (res != null) {
                TestStepResultDataObjectDistributor.getInstance().
                        distributeData(res);
            }
        }
    }

    /**
     * Cancelling running task for the given dataobject
     * @param data
     */
    public final void cancelTask(TestStepDataObject data) {
        m_threadExecutorPool.cancelTask(data.getMessageId());

    }

    public final void cancelTask(String messageId) {
        m_threadExecutorPool.cancelTask(messageId);

    }

    public void abortAllTasks(Boolean dataObj) {

        m_threadExecutorPool.abortAllTasks();
    }

    /**
     * Closes thread pool
     * @throws java.lang.Throwable
     */
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        if (m_threadExecutorPool != null) {
            m_threadExecutorPool.shutdown();
            m_threadExecutorPool = null;
        }
    }
}
